#pragma once
#include <functional>
#include "common.hpp"
#include "Socket.hpp"

using namespace SocketModule;

// client -> server  客户的请求：客户需要将请求序列化到服务端，服务端需要将客户的请求反序列化
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper)
        : _x(x),
          _y(y),
          _oper(oper)
    {
    }

    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter Writer;
        std::string s = Writer.write(root);
        return s;
    }

    bool Deserialize(std::string& Package)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(Package, root); // 将Json串读到root中
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }

    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

    ~Request()
    {
    }

private:
    int _x;
    int _y;
    char _oper;
};

// server -> client  服务端需要将业务处理的结果序列化到客户端，客户端需要反序列业务处理的结果
class Response
{
public:
    Response() {}

    Response(int result, int code) : _result(result), _code(code)
    {
    }

    // 服务端向用户端序列化
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }
    // 用户端反序列从服务端接收到的数据
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }

    void SetResult(int result)
    {
        _result = result;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void ShowResult()
    {
        std::cout << "计算结果是：" << _result << " [" << _code << "]" << std::endl;
    }

    ~Response() {}

private:
    int _result;
    int _code;
};

const std::string seq = "\r\n";
using func_t = std::function<Response(Request &req)>;

class Protocol
{
public:
    Protocol(func_t func)
        : _func(func)
    {
    }

    Protocol()
    {
    }

    // 编码 Encode      len/r/n json码 /r/n  约定通信的双方以这种方式(协议)进行通信，json码为有效数据
    std::string Encode(std::string &jsonstr)
    {
        std::string len = std::to_string(jsonstr.size());       //
        return (len + seq + jsonstr + seq);
    }

    // 解码 Decode 通信的双方以该协议进行通信
    bool Decode(std::string &buffer, std::string *Json_Package)
    {
        // 通信的双方通过 数据长度 + /r/n + json串 + /r/n 进行加密
        // 1.先找第一个 /r/n，没找到说明数据不完整

        ssize_t pos = buffer.find(seq);
        if (pos == std::string::npos)
        {   
            return false;
        }
            // 到这说明该报文有数据长度
        // 2.获得数据长度
        std::string package_len_str = buffer.substr(0, pos);
        int len = std::stoi(package_len_str);


        // 3.根据加密协议 以及数据长度，得到有效报文的总长度
        int size = package_len_str.size() + 2 * seq.size() + len;


        // 4.如果当前服务端收到的数据长度小于 size  说明收到的消息不完整
        if (buffer.size() < size)
        {   
            return false;
        }

        // 5.到这说明buffer内至少包含一条完整的加密后数据，对加密数据进行解密
        *Json_Package = buffer.substr(pos + 2, len);

        // 6.将解密后的数据从buffer中删除
        buffer.erase(0, size);

        return true;
    }
    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string buffer_queue;
        while (true)
        {
            int n = sock->Recv(&buffer_queue);
            if (n > 0)
            {
                // 读取不完整，避免粘包问题
                // 服务端从用户端读取用户请求  → 经客户端序列化的数据且加密的数据
                // 1. 服务端解密
                std::string Json_Package;
                while (Decode(buffer_queue, &Json_Package))
                {

                    // 2.服务端对客户请求的反序列化
                    Request req;
                    bool ret = req.Deserialize(Json_Package);
                    if (!ret)
                        continue;

                    // 3. 解密反序列化完毕后 调用上层业务
                    

                    Response resp = _func(req); // 要将业务处理的结果返回给客户端，所以需要返回一个Response对象

                    // 将得到的结果序列化传递给 用户端
                    // 4.先序列化  服务端 → 用户端的序列化
                    std::string send_str = resp.Serialize();

                    // 5.序加密
                    std::string package = Encode(send_str);
                    // 6.发送
                    sock->Send(package);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "用户退出了";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client" << client.StringAddr() << ": recv error";
                break;
            }
        }
    }

    bool GetResponse(std::shared_ptr<Socket> client, std::string &resp_buffer, Response *resp)
    {
        while (true)
        {
            int n = client->Recv(&resp_buffer);
            if (n > 0)
            {
                std::string json_package;
                while (Decode(resp_buffer, &json_package))
                {
                    resp->Deserialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
                return false;
            }
            else
            {
                return false;
            }
        }
    }

    std::string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);
        // 将客户端的请求序列化
        std::string json_str = req.Serialize();
        // 将序列化的json串加密
        return Encode(json_str);
    }

    ~Protocol()
    {
    }

private:
    // 因为我们用的是多进程
    // Request _req;
    // Response _resp;
    func_t _func;
};